package br.com.rglariguet.pioneer.controller.asc;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import br.com.rglariguet.pioneer.controller.ControllerComum;
import br.com.rglariguet.pioneer.dao.AutorizadaDAO;
import br.com.rglariguet.pioneer.dao.ClienteDAO;
import br.com.rglariguet.pioneer.dao.DadosBasicosProdutoDAO;
import br.com.rglariguet.pioneer.dao.DadosFechamentoReparoDAO;
import br.com.rglariguet.pioneer.dao.DefeitoDAO;
import br.com.rglariguet.pioneer.dao.DefeitoPioneerDAO;
import br.com.rglariguet.pioneer.dao.EnderecoDAO;
import br.com.rglariguet.pioneer.dao.PecaDAO;
import br.com.rglariguet.pioneer.dao.PedidoDoReparoDAO;
import br.com.rglariguet.pioneer.dao.PedidoPecaDAO;
import br.com.rglariguet.pioneer.dao.ProdutoDAO;
import br.com.rglariguet.pioneer.dao.ReparoDAO;
import br.com.rglariguet.pioneer.enums.SituacaoPedidoPecaEnum;
import br.com.rglariguet.pioneer.enums.StatusReparoUsuarioEnum;
import br.com.rglariguet.pioneer.filtropesquisa.FiltroReparo;
import br.com.rglariguet.pioneer.modelos.Autorizada;
import br.com.rglariguet.pioneer.modelos.DadosBasicosProduto;
import br.com.rglariguet.pioneer.modelos.Defeito;
import br.com.rglariguet.pioneer.modelos.DefeitoDoReparo;
import br.com.rglariguet.pioneer.modelos.DefeitoPioneer;
import br.com.rglariguet.pioneer.modelos.PedidoDoReparo;
import br.com.rglariguet.pioneer.modelos.PedidoPeca;
import br.com.rglariguet.pioneer.modelos.Reparo;
import br.com.rglariguet.pioneer.sap.ReparoSAP;
import br.com.rglariguet.pioneer.util.MensagemTela;
import br.com.rglariguet.pioneer.util.PecaUtil;
import br.com.rglariguet.pioneer.wrapper.ListaReparoWrapper;

import com.google.common.collect.Lists;
import com.google.gson.Gson;

@Controller
@RequestMapping("/seguro/asc/")
public class ReparoController extends ControllerComum {

	@Autowired
	private ProdutoDAO produtoDao;

	@Autowired
	private ReparoDAO reparoDao;

	@Autowired
	private ClienteDAO clienteDao;

	@Autowired
	private EnderecoDAO enderecoDao;

	@Autowired
	private DadosBasicosProdutoDAO dadosBasicosProdutoDao;
	
	@Autowired
	private PecaDAO pecaDao;
	
	@Autowired
	private DefeitoPioneerDAO defeitoPioneerDao;
	
	@Autowired
	private DefeitoDAO defeitoDao;
	
	@Autowired
	private DadosFechamentoReparoDAO dadosFechamentoDao;
	
	@Autowired
	PedidoPecaDAO pedidoPecaDao;
	
	@Autowired
	private PedidoDoReparoDAO pedidoDoReparoDao;
	
	@Autowired
	private AutorizadaDAO autorizadaDao;
	
	private Reparo reparo = new Reparo();
	
	@ModelAttribute("reparo")
	public Reparo getReparo() {
		return this.reparo;
	}
	
	public void setReparo(Reparo reparo) {
		this.reparo = reparo;
	}

	@RequestMapping("entradaDeReparo")
	public ModelAndView abreTelaEntradaDeReparo(MensagemTela msg, boolean isRetornoValidacao, Reparo reparo) {
		ModelAndView mv = new ModelAndView("/seguro/asc/entradaDeReparo");
		mv.addObject("dadosBasicos", dadosBasicosProdutoDao.listarTodos());
		mv.addObject("msg", msg.getTipoMensagem() != null ? msg : null);
		
		if (reparo != null) {
			if (reparo.getStatus() != StatusReparoUsuarioEnum.ABERTO) {
				mv.addObject("pedidoPeca", new PedidoPeca());
				mv.addObject("defeitosPioneer", defeitoPioneerDao.listarTodos());
			}
			mv.addObject("reparo", reparo);
		}
		
		if (!isRetornoValidacao) {
			mv.addObject("reparo", new Reparo());
			getReparo().setPedidoDoReparo(new PedidoDoReparo());
			getReparo().setDefeitoDoReparo(new DefeitoDoReparo());
		}
		return mv;
	}

	@RequestMapping("incluirReparo")
	public ModelAndView salvar(@Valid Reparo reparo, BindingResult br, HttpSession session) {
		if (!br.hasErrors()) {
			reparo.setNomeCriadorReparo((String)session.getAttribute("usuarioLogado"));
			Autorizada autorizadaCriadoraDoReparo = autorizadaDao.buscaPorNome(reparo.getNomeCriadorReparo());
			Reparo reparoComNumeroOs = new ReparoSAP().criarReparoSAP(reparo, autorizadaCriadoraDoReparo);
			
			reparoComNumeroOs.setStatus(StatusReparoUsuarioEnum.ABERTO);
			salvaOuAtualizaReparo(reparoComNumeroOs);
			
			return abreTelaEntradaDeReparo(criaMsgSucesso("reparo.salvo.sucesso"), false, null);
		}
		return abreTelaEntradaDeReparo(criaMsgErro("reparo.salvo.erro"), true, null);
	}
	
	@RequestMapping("gravarPedidoPecaReparo")
	public ModelAndView gravarPedidoPeca() {
		for (PedidoPeca pedidoPeca : getReparo().getPedidoDoReparo().getPedidosPeca()) {
			pedidoPecaDao.salvar(pedidoPeca);
		}
		getReparo().setStatus(StatusReparoUsuarioEnum.AGUARDANDO_PECA);
		reparoDao.alterar(getReparo());
		return abreTelaEntradaDeReparo(criaMsgSucesso("pedido.realizado.sucesso"), true, getReparo());
	}
	
	
	@RequestMapping("gravarDetalheDefeitoReparo")
	public ModelAndView gravarDetalhesDefeito() {
		for (Defeito defeito : getReparo().getDefeitoDoReparo().getDefeitos()) {
			defeitoDao.salvar(defeito);
		}
		
		reparoDao.alterar(getReparo());
		return abreTelaEntradaDeReparo(criaMsgSucesso("detalhes.defeito.salvo"), true, getReparo());
	}

	
	private void salvaOuAtualizaReparo(Reparo reparo) {
		preparaReparoParaSalvar(reparo);
		gravaProduto(reparo);
		gravaEndereco(reparo);
		gravaCliente(reparo);
		gravaReparo(reparo);
	}

	private void gravaReparo(Reparo reparo) {
		if (reparo.getId() == 0) {
			reparoDao.salvar(reparo);
		}else{
			reparoDao.alterar(reparo);
		}
	}

	private void gravaCliente(Reparo reparo) {
		if (reparo.getCliente().getId() == 0) {
			clienteDao.salvar(reparo.getCliente());
		}else{
			clienteDao.alterar(reparo.getCliente());
		}
	}

	private void preparaReparoParaSalvar(Reparo reparo) {
		DadosBasicosProduto dadosBasicosDoModeloSelecionado = dadosBasicosProdutoDao
				.buscaPorModelo(reparo.getProduto().getDadosBasicos().getModelo());
		reparo.getProduto().setDadosBasicos(dadosBasicosDoModeloSelecionado);
		reparo.setDataDeModificacao(Calendar.getInstance());
	}

	private void gravaEndereco(Reparo reparo) {
		if (reparo.getCliente().getEndereco().getId() == 0) {
			enderecoDao.salvar(reparo.getCliente().getEndereco());
		}else{
			enderecoDao.alterar(reparo.getCliente().getEndereco());
		}
	}

	private void gravaProduto(Reparo reparo) {
		if (reparo.getProduto().getId() == 0) {
			produtoDao.salvar(reparo.getProduto());
		}else{
			produtoDao.alterar(reparo.getProduto());
		}
	}

	@RequestMapping("buscarReparos")
	public ModelAndView consultar(FiltroReparo filtroReparo, HttpSession session) {
		ListaReparoWrapper reparoWrapper = new ListaReparoWrapper();
		filtroReparo.setNomeCriadorReparo((String)session.getAttribute("usuarioLogado"));
		reparoWrapper.setReparos(reparoDao.listarComFiltro(filtroReparo));
		return abreTelaConsultaDeReparo(reparoWrapper, true);
	}

	@RequestMapping("consultaDeReparo")
	public ModelAndView abreTelaConsultaDeReparo(ListaReparoWrapper reparoWrapper, boolean isRetornoConsulta) {
		ModelAndView mv = new ModelAndView("/seguro/asc/consultaDeReparo");
		mv.addObject("dadosBasicos", dadosBasicosProdutoDao.listarTodos());
		mv.addObject("reparos", reparoWrapper.getReparos());
		mv.addObject("status", Arrays.asList(StatusReparoUsuarioEnum.values()));
		if (!isRetornoConsulta) {
			mv.addObject("filtroReparo", new FiltroReparo());
		} else {
			if (reparoWrapper.getReparos().isEmpty()) {
				mv.addObject("msg", criaMsgErro("reparo.nao.encontrado"));
			}
		}
		return mv;
	}
	

	@RequestMapping("editarReparo")
	public ModelAndView abreTelaEdicaoReparo(long id, HttpSession session) {
		setReparo(reparoDao.buscaPorId(id, (String)session.getAttribute("usuarioLogado")));
		
		return abreTelaEntradaDeReparo(new MensagemTela(), true, getReparo());
	}
	
	
	
	@RequestMapping("adicionaPecaAoReparo")
	public @ResponseBody String  adicionaPeca(@Valid PedidoPeca pedidoPeca, BindingResult br) {
		if (br.hasFieldErrors("quantidade") || br.hasFieldErrors("peca.codigo")) {
			return "inclusao.peca.erro.campos";
		}

		
		if (!PecaUtil.validaPecaComTraco(pedidoPeca.getPeca().getCodigo())) {
			return "peca.nao.encontrada";
		}
		
		
		if (!PecaUtil.pecaExiste(pedidoPeca.getPeca().getCodigo(), pecaDao)) {
			return "peca.nao.encontrada";
		}
		
		pedidoPeca.setPeca(pecaDao.buscaPorCodigo(pedidoPeca.getPeca().getCodigo().split(" - ")[0]));

		boolean existeNaLista = false;
		for (PedidoPeca pedidoPecaDaLista : getReparo().getPedidoDoReparo().getPedidosPeca()) {
			if (pedidoPecaDaLista.getPeca().getCodigo().equals(pedidoPeca.getPeca().getCodigo())) {
				pedidoPecaDaLista.setQuantidade(pedidoPecaDaLista.getQuantidade() + pedidoPeca.getQuantidade());
				existeNaLista = true;
			}
		}
		if (!existeNaLista) {
			pedidoPeca.setStatus(SituacaoPedidoPecaEnum.PENDENTE);
			getReparo().getPedidoDoReparo().getPedidosPeca().add(pedidoPeca);
		}
		return new Gson().toJson(pedidoPeca);
	}

	
	@RequestMapping("adicionaDefeitoAoReparo")
	public @ResponseBody String adicionaDefeitoAoReparo(@Valid Defeito defeito, BindingResult br) {
		if (br.hasErrors()) {
			return "sintoma.defeito.solucao.vazio";
		}
		
		getReparo().getDefeitoDoReparo().getDefeitos().add(defeito);
		
		return new Gson().toJson(defeito);
	}
	
	@RequestMapping("excluirDefeito")
	public @ResponseBody void excluiDefeito(DefeitoPioneer defeitoPioneer, HttpServletResponse resp) {
		for (int i = 0; i< getReparo().getDefeitoDoReparo().getDefeitos().size(); i++) {
			Defeito defeito = getReparo().getDefeitoDoReparo().getDefeitos().get(i);
			if (defeito.getSintoma().equals(defeitoPioneer.getSintoma())
					&& defeito.getDefeito().equals(defeitoPioneer.getDefeito())
					&& defeito.getSolucao().equals(defeitoPioneer.getSolucao())) {
				
				getReparo().getDefeitoDoReparo().getDefeitos().remove(i);
				break;
				
			}
		}
		resp.setStatus(200);
	}
	
	
	@RequestMapping("finalizarReparo")
	public ModelAndView finalizarReparo(Reparo reparo) {
		
		getReparo().setStatus(StatusReparoUsuarioEnum.ENVIADO_PIONEER);
		
		ArrayList<Defeito> listaReparos = Lists.newArrayList(getReparo().getDefeitoDoReparo().getDefeitos());
		for (Defeito defeito : listaReparos) {
			if (defeito.getId() == 0) {
				getReparo().getDefeitoDoReparo().getDefeitos().remove(defeito);
			}
		}
		salvaOuAtualizaReparo(getReparo());
		return abreTelaEntradaDeReparo(criaMsgSucesso("reparo.finalizado"), true, getReparo());
	}


}
